package com.wit.health.fragment;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;


import com.google.gson.Gson;
import com.tli.walkanalysis.WalkingAnalysisServiceApi;


import com.wit.health.R;
import com.wit.health.share.SharedViewModel;
import com.wit.health.spp.Bwt901cl;
import com.wit.health.spp.data.WitSensorKey;
import com.wit.health.spp.interfaces.IBwt901clRecordObserver;
import com.wit.health.util.StringToCSV;
import com.wit.witsdk.sensor.dkey.ShortKey;
import com.wit.witsdk.sensor.modular.connector.modular.bluetooth.BluetoothBLE;
import com.wit.witsdk.sensor.modular.connector.modular.bluetooth.BluetoothSPP;
import com.wit.witsdk.sensor.modular.connector.modular.bluetooth.WitBluetoothManager;
import com.wit.witsdk.sensor.modular.connector.modular.bluetooth.exceptions.BluetoothBLEException;
import com.wit.witsdk.sensor.modular.connector.modular.bluetooth.interfaces.IBluetoothFoundObserver;
import com.wit.witsdk.sensor.modular.device.exceptions.OpenDeviceException;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.LinkedBlockingQueue;


import android.widget.EditText;
import android.widget.Switch;



import com.tli.bluetooth.PreferenceData;
import com.tli.common.AAData;
import com.tli.common.ATData;
import com.tli.common.CommonAttribute;
import com.tli.common.FsrData;
import com.tli.common.GAData;
import com.tli.common.MVData;
import com.tli.common.MpuData;
import com.tli.common.RunningData;
import com.tli.common.RunningSectionData;
import com.tli.common.SAData;
import com.tli.utils.ApiBuildConfig;
import com.tli.walkanalysis.DeviceInfo;
import com.tli.walkanalysis.ScanData;
import com.tli.walkanalysis.UIServiceCallbackInterface;
import com.wit.health.util.CSVWriter;

import androidx.core.content.ContextCompat;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;


/**  
* 主页Fragment  
*  
* @Author liaozhaoping 
* @Date 2024/5/21 16:49  
*/
public class HomeFragment extends Fragment implements IBluetoothFoundObserver, IBwt901clRecordObserver,UIServiceCallbackInterface {

    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private static final String TAG = "HomeFragment";
    private List<Bwt901cl> bwt901clList = new ArrayList<>();
    private boolean destroyed = true;
    private File internalStorageDir;
    private TextView deviceDataTextView;

    private Thread refreshDataThread;

    // fragment之间共享数据
    private SharedViewModel viewModel;

    // 画图用的表格
//    private LineChart chart;

    private String[] permissions = {
            android.Manifest.permission.READ_EXTERNAL_STORAGE,
            android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
            android.Manifest.permission.ACCESS_COARSE_LOCATION,
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.ACCESS_FINE_LOCATION
    };
    private static final int MULTIPLE_PERMISSIONS = 101;

    private static final int MAX_RETRY_COUNT = 3; // 最大重试次数
    private static final long RETRY_INTERVAL_MS = 5000; // 重试间隔时间（毫秒）

    private Context mContext;
    private static final int REQUEST_ENABLE_BT = 1;
    private BluetoothAdapter mBluetoothAdapter;
    private String mLeftAddress = "00:00:00:00:00:00";
    private boolean mLeftScaned = false;

    private String mRightAddress = "00:00:00:00:00:01";
    private boolean mRightScaned = false;

    private String[] mDeviceAddresses = new String[2];

    boolean mFootFileViewEnable = false;
    private Object mWaitLock = new Object();
    private static LinkedBlockingQueue<HomeFragment.DataQueuePacket> dataQueue = null;

    int new_type_index = 0;

    private TextView leftInsoleDataTextView;

    private TextView rightInsoleDataTextView;

    private String username;

    private Handler handler = new Handler(Looper.getMainLooper());

    class DataQueuePacket {
        int lr_type;
        byte[] org;

        public void setData(int lrtype, byte[] bytedata) {
            this.lr_type = lrtype;
            this.org = bytedata.clone();
        }
    }





    public HomeFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment HomeFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static HomeFragment newInstance(String param1, String param2) {
        HomeFragment fragment = new HomeFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
            username = getArguments().getString("USERNAME_KEY");
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment

        View view = inflater.inflate(R.layout.fragment_home, container, false);
        deviceDataTextView = view.findViewById(R.id.deviceDataTextView);
        leftInsoleDataTextView = view.findViewById(R.id.leftInsoleDataTextView);
        rightInsoleDataTextView = view.findViewById(R.id.rightInsoleDataTextView);
        // chart = view.findViewById(R.id.chart);
        // 启动刷新数据的线程
        //new Thread(this::refreshDataTh).start();

        mContext = getContext();
        checkPermissions();
        internalStorageDir = mContext.getFilesDir();

        boolean emulator = false;
        if (!emulator) {
            if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
                Toast.makeText(mContext, "Ble not supported", Toast.LENGTH_SHORT).show();
                getActivity().finish();
            }

            final BluetoothManager mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = mBluetoothManager.getAdapter();
            if (mBluetoothAdapter == null) {
                Toast.makeText(mContext, "Ble not supported", Toast.LENGTH_SHORT).show();
                getActivity().finish();
                return view;
            }

            if (!mBluetoothAdapter.isEnabled()) {
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                if (ActivityCompat.checkSelfPermission(mContext, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
                    return view;
                }
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
                return view;
            }
        }

        dataQueue = new LinkedBlockingQueue<>();
        dataQueue.clear();

        mFootFileViewEnable = true;
        Thread th = new Thread(mFootFileViewRunnable);
        th.start();

        int ret = WalkingAnalysisServiceApi.createBleService(getContext(), this);
        Log.e(TAG, "create ret " + ret);

        setupUI(view);

        return view;

    }

    private void setupUI(View rootView) {
        rootView.findViewById(R.id.scanstop).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                WalkingAnalysisServiceApi.stopDeviceScan();
            }
        });
        rootView.findViewById(R.id.scanstart).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                WalkingAnalysisServiceApi.startDeviceScan();
            }
        });
        rootView.findViewById(R.id.realstart).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int ret = WalkingAnalysisServiceApi.StartAnalysis();
                Log.e(TAG, "StartAnalysis ret " + ret);
            }
        });
        rootView.findViewById(R.id.realstop).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int ret = WalkingAnalysisServiceApi.StopAnalysis();
            }
        });
        rootView.findViewById(R.id.connect).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String[] data = WalkingAnalysisServiceApi.getUserInfo();
                if (data != null) {
                    data[WalkingAnalysisServiceApi.KEY_MY_FOOT_SIZE_INDEX] = "260";
                    data[WalkingAnalysisServiceApi.KEY_MY_AGE_INDEX] = "30";
                    data[WalkingAnalysisServiceApi.KEY_MY_HEIGHT_INDEX] = "180";
                    data[WalkingAnalysisServiceApi.KEY_MY_WEIGHT_INDEX] = "70";
                    data[WalkingAnalysisServiceApi.KEY_MY_SEX_INDEX] = "M";
                    data[WalkingAnalysisServiceApi.KEY_MY_NAME_INDEX] = "user";
                    data[WalkingAnalysisServiceApi.KEY_MY_EMAIL_INDEX] = "user@mgmail.co.kr";
                    WalkingAnalysisServiceApi.setUserInfo(data);
                }
                data = WalkingAnalysisServiceApi.getDeviceAddress();
                if (data != null) {
                    mDeviceAddresses[0] = data[WalkingAnalysisServiceApi.KEY_LEFT_ADDRESS_INDEX];
                    mDeviceAddresses[1] = data[WalkingAnalysisServiceApi.KEY_RIGHT_ADDRESS_INDEX];
                    Log.e(TAG, "left insole addr " + mDeviceAddresses[0] + " right insole addr " + mDeviceAddresses[1]);
                    if (mDeviceAddresses[0].equals("00:00:00:00:00:00") && mDeviceAddresses[1].equals("00:00:00:00:00:01")) {
                        data[WalkingAnalysisServiceApi.KEY_LEFT_ADDRESS_INDEX] = mLeftAddress;
                        data[WalkingAnalysisServiceApi.KEY_RIGHT_ADDRESS_INDEX] = mRightAddress;
                        WalkingAnalysisServiceApi.setDeviceAddress(data);
                    }
                    WalkingAnalysisServiceApi.setDeviceAddress(data);
                }
                //等待这段代码完成后再执行后面的代码
                WalkingAnalysisServiceApi.bleConnect((byte) 0, false, false);

                // 判断是否连接成功
//                boolean ret =WalkingAnalysisServiceApi.setDeviceFind(CommonAttribute.LEFT_TYPE);
//                if (ret) {
//                    Toast.makeText(mContext, "connect Successful", Toast.LENGTH_SHORT).show();
//                } else {
//                    Toast.makeText(mContext, "connect Failed", Toast.LENGTH_SHORT).show();
//                }

            }
        });
        rootView.findViewById(R.id.disconnect).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                WalkingAnalysisServiceApi.bleDisconnect();
            }
        });
        // Set other ClickListeners similarly...
        rootView.findViewById(R.id.setfinddevice).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean ret =WalkingAnalysisServiceApi.setDeviceFind(CommonAttribute.LEFT_TYPE);
                if (ret) {
                    Toast.makeText(mContext, "setDeviceFind Successful", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(mContext, "setDeviceFind Failed", Toast.LENGTH_SHORT).show();
                }
            }
        });

        rootView.findViewById(R.id.getfinddevice).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean ret = WalkingAnalysisServiceApi.getDeviceFind(CommonAttribute.LEFT_TYPE);
                if (ret) {
                    Toast.makeText(mContext, "connected insole Successful", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(mContext, "connected insole Failed", Toast.LENGTH_SHORT).show();
                }
            }
        });

        rootView.findViewById(R.id.setuserinfo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean ret =WalkingAnalysisServiceApi.setDeviceInformation((byte)CommonAttribute.REGISTER_TYPE_NEW_REGISTER);
            }
        });

        rootView.findViewById(R.id.setuserinfochange).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean ret =WalkingAnalysisServiceApi.setDeviceInformation((byte)CommonAttribute.REGISTER_TYPE_CHANGE_USERINFO);
            }
        });
        rootView.findViewById(R.id.workinfo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int ret =WalkingAnalysisServiceApi.setRequestStatus((byte) (CommonAttribute.REQUEST_STATUS_AT_ENABLE | CommonAttribute.REQUEST_STATUS_AA_ENABLE | CommonAttribute.REQUEST_STATUS_GA_ENABLE | CommonAttribute.REQUEST_STATUS_MV_ENABLE));
            }
        });

        rootView.findViewById(R.id.getfwinfo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean ret =WalkingAnalysisServiceApi.getFirmwareStatus();
            }
        });

        rootView.findViewById(R.id.clearall).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String[] deviceInfoPreference = PreferenceData.getDeviceInfoPreference(getContext());
                deviceInfoPreference[PreferenceData.left_device_address_index] = "00:00:00:00:00:00";
                deviceInfoPreference[PreferenceData.right_device_address_index] = "00:00:00:00:00:01";
                PreferenceData.setDeviceInfoPreference(mContext,deviceInfoPreference);

                boolean ret =WalkingAnalysisServiceApi.setClearAll();
            }
        });

        rootView.findViewById(R.id.historyclear).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean ret =WalkingAnalysisServiceApi.setClearHistory(CommonAttribute.STORAGE_DAY_HOUR_CLEAR);
            }
        });

        rootView.findViewById(R.id.at_day).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Switch s = rootView.findViewById(R.id.history_type_switch);
                if(s.isChecked()){
                    Log.e(TAG,"Check");
                    new_type_index++;
                    // 인텍스 변화만 준다.(It only gives index changes.)
                    if(new_type_index>250)
                        new_type_index = 0;
                    WalkingAnalysisServiceApi.RequestStorageATDataLRType(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_DAY ,new_type_index, CommonAttribute.STORAGE_REPORT_TYPE_NEW);

                }else{
                    Log.e(TAG,"Un Check");

                    EditText e = rootView.findViewById(R.id.editTextNumberDecimalDay);
                    if(e.getText().toString().length() <= 0)
                        return;

                    int day_index = Integer.parseInt(e.getText().toString());

                    WalkingAnalysisServiceApi.RequestStorageATDataLRType(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_DAY ,day_index, CommonAttribute.STORAGE_REPORT_TYPE_SELECT);

                }
            }
        });

        rootView.findViewById(R.id.at_hour).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Switch s = rootView.findViewById(R.id.history_type_switch);
                if (s.isChecked()) {
                    Log.e(TAG, "Check");
                    new_type_index++;
                    // 인텍스 변화만 준다.(It only gives index changes.)
                    if (new_type_index > 250)
                        new_type_index = 0;


                    WalkingAnalysisServiceApi.RequestStorageATDataLRType(CommonAttribute.LEFT_TYPE, CommonAttribute.STORAGE_TYPE_HOUR, new_type_index, CommonAttribute.STORAGE_REPORT_TYPE_NEW);

                } else {
                    Log.e(TAG, "Un Check");

                    EditText e = rootView.findViewById(R.id.editTextNumberDecimalHour);
                    if (e.getText().toString().length() <= 0)
                        return;
                    int day_index = Integer.parseInt(e.getText().toString());

                    WalkingAnalysisServiceApi.RequestStorageATDataLRType(CommonAttribute.LEFT_TYPE, CommonAttribute.STORAGE_TYPE_HOUR, day_index, CommonAttribute.STORAGE_REPORT_TYPE_SELECT);
                }
            }
        });

        rootView.findViewById(R.id.aa_day).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Switch s = rootView.findViewById(R.id.history_type_switch);
                if(s.isChecked()){
                    Log.e(TAG,"Check");
                    new_type_index++;
                    if(new_type_index>250)
                        new_type_index = 0;
                    WalkingAnalysisServiceApi.RequestStorageAADataLRType(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_DAY ,new_type_index, CommonAttribute.STORAGE_REPORT_TYPE_NEW);
                }else{
                    Log.e(TAG,"Un Check");
                    EditText e = rootView.findViewById(R.id.editTextNumberDecimalDay);
                    if(e.getText().toString().length() <= 0)
                        return;
                    int day_index = Integer.parseInt(e.getText().toString());
                    WalkingAnalysisServiceApi.RequestStorageAADataLRType(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_DAY ,day_index, CommonAttribute.STORAGE_REPORT_TYPE_SELECT);
                }

            }
        });

        rootView.findViewById(R.id.aa_hour).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Switch s = rootView.findViewById(R.id.history_type_switch);
                if(s.isChecked()){
                    Log.e(TAG,"Check");
                    new_type_index++;
                    // 인텍스 변화만 준다.(It only gives index changes.)
                    if(new_type_index>250)
                        new_type_index = 0;
                    WalkingAnalysisServiceApi.RequestStorageAADataLRType(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_HOUR ,new_type_index, CommonAttribute.STORAGE_REPORT_TYPE_NEW);

                }else{
                    Log.e(TAG,"Un Check");
                    EditText e = rootView.findViewById(R.id.editTextNumberDecimalHour);
                    if(e.getText().toString().length() <= 0)
                        return;
                    int day_index = Integer.parseInt(e.getText().toString());
                    WalkingAnalysisServiceApi.RequestStorageAADataLRType(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_HOUR ,day_index, CommonAttribute.STORAGE_REPORT_TYPE_SELECT);

                }
            }
        });

        rootView.findViewById(R.id.ga_day).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Switch s = rootView.findViewById(R.id.history_type_switch);
                if(s.isChecked()){
                    Log.e(TAG,"Check");
                    new_type_index++;
                    if(new_type_index>250)
                        new_type_index = 0;
                    WalkingAnalysisServiceApi.RequestStorageGAData(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_DAY ,new_type_index, CommonAttribute.STORAGE_REPORT_TYPE_NEW);


                }else{
                    Log.e(TAG,"Un Check");
                    EditText e = rootView.findViewById(R.id.editTextNumberDecimalDay);
                    if(e.getText().toString().length() <= 0)
                        return;
                    int day_index = Integer.parseInt(e.getText().toString());
                    WalkingAnalysisServiceApi.RequestStorageGAData(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_DAY ,day_index, CommonAttribute.STORAGE_REPORT_TYPE_SELECT);
                }
            }
        });

        rootView.findViewById(R.id.ga_hour).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Switch s = rootView.findViewById(R.id.history_type_switch);
                if(s.isChecked()){
                    Log.e(TAG,"Check");
                    new_type_index++;
                    if(new_type_index>250)
                        new_type_index = 0;
                    WalkingAnalysisServiceApi.RequestStorageGAData(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_HOUR ,new_type_index, CommonAttribute.STORAGE_REPORT_TYPE_NEW);

                }else{
                    Log.e(TAG,"Un Check");
                    EditText e = rootView.findViewById(R.id.editTextNumberDecimalHour);
                    if(e.getText().toString().length() <= 0)
                        return;
                    int day_index = Integer.parseInt(e.getText().toString());

                    WalkingAnalysisServiceApi.RequestStorageGAData(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_HOUR ,day_index, CommonAttribute.STORAGE_REPORT_TYPE_SELECT);

                }
            }
        });

        rootView.findViewById(R.id.mv_day).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Switch s = rootView.findViewById(R.id.history_type_switch);
                if(s.isChecked()){
                    Log.e(TAG,"Check");
                    new_type_index++;
                    if(new_type_index>250)
                        new_type_index = 0;

                    WalkingAnalysisServiceApi.RequestStorageMVData(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_DAY ,new_type_index, CommonAttribute.STORAGE_REPORT_TYPE_NEW);
                }else{
                    Log.e(TAG,"Un Check");
                    EditText e = rootView.findViewById(R.id.editTextNumberDecimalDay);
                    if(e.getText().toString().length() <= 0)
                        return;
                    int day_index = Integer.parseInt(e.getText().toString());
                    WalkingAnalysisServiceApi.RequestStorageMVData(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_DAY ,day_index, CommonAttribute.STORAGE_REPORT_TYPE_SELECT);
                }
            }
        });

        rootView.findViewById(R.id.mv_hour).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Switch s = rootView.findViewById(R.id.history_type_switch);
                if(s.isChecked()){
                    Log.e(TAG,"Check");
                    new_type_index++;
                    if(new_type_index>250)
                        new_type_index = 0;

                    WalkingAnalysisServiceApi.RequestStorageMVData(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_HOUR ,new_type_index, CommonAttribute.STORAGE_REPORT_TYPE_NEW);

                }else{
                    Log.e(TAG,"Un Check");

                    EditText e = rootView.findViewById(R.id.editTextNumberDecimalHour);
                    if(e.getText().toString().length() <= 0)
                        return;
                    int day_index = Integer.parseInt(e.getText().toString());
                    WalkingAnalysisServiceApi.RequestStorageMVData(CommonAttribute.LEFT_TYPE,CommonAttribute.STORAGE_TYPE_HOUR ,day_index, CommonAttribute.STORAGE_REPORT_TYPE_SELECT);

                }
            }
        });

        rootView.findViewById(R.id.fwupdate).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int fwVer = 83;
                String fwFileNmL = "IKW_V83_20240105_L.ZIP";
            }
        });

     }

    public void CreateWalkAnalysisService(){
        int ret = WalkingAnalysisServiceApi.createBleService(mContext,this);
        Log.e(TAG, "createBleService " + ret);
    }

    Runnable mFootFileViewRunnable = new Runnable(){
        @Override
        public void run() {

            int [] fdata = new int[4];
            Log.e(TAG, TAG+" Thread start");
            while(mFootFileViewEnable){

                synchronized (mWaitLock) {
                    if(dataQueue == null)
                        return;

                    if(dataQueue.size()  > 0){
                        DataQueuePacket packet = null;
                        try {
                            packet = dataQueue.take();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        byte arg0 [] = packet.org;


                        if (packet.lr_type == CommonAttribute.LEFT_TYPE) {
                            ArrayList<MpuData> mpulist = WalkingAnalysisServiceApi.getImuDataList(CommonAttribute.LEFT_TYPE, arg0);
                            ArrayList<FsrData> fsrlist = WalkingAnalysisServiceApi.getFsrDataList(CommonAttribute.LEFT_TYPE);
                            for (int i = 0; i < fsrlist.size(); i++) {
                                FsrData fsrdata = fsrlist.get(i);
                                MpuData mpudata = mpulist.get(i);
                                // System.out.println(" Left X:" + mpudata.mMpu[0] + " Y:" + mpudata.mMpu[1] + " Z:" + mpudata.mMpu[2]);
                                // System.out.println(" Left f1:" + fsrdata.mFsr[0] + " f2:" + fsrdata.mFsr[1] + " f3:" + fsrdata.mFsr[2]+ " f4:" + fsrdata.mFsr[3]);
                                long timestamp = System.currentTimeMillis();
                                String dataStr = mpudata.mMpu[0] + " " + mpudata.mMpu[1] + " " + mpudata.mMpu[2] + " " + fsrdata.mFsr[0] + " " + fsrdata.mFsr[1] + " " + fsrdata.mFsr[2] + " " + fsrdata.mFsr[3];

                                String leftInsoleData = String.valueOf(timestamp) + " " + dataStr;
                                // String url = "http://192.168.111.176:5000/leftInsoleData";
                                Map<String, String> dataMap = new HashMap<>();
                                dataMap.put("leftInsoleData", leftInsoleData);
                                dataMap.put("username", username);
                                // 创建一个 Gson 对象
                                Gson gson = new Gson();
                                // 将 Map 转换为 JSON 字符串
                                String jsonData = gson.toJson(dataMap);
                                // 异步发送数据
//                                NetUtil.sendPostAsync(NetConstant.SEND_LEFTINSOLEDATA_URL, jsonData, new Callback() {
//                                    @Override
//                                    public void onFailure(Call call, IOException e) {
//                                        // 处理请求失败的情况
//                                        System.err.println("Failed to send data: " + e.getMessage());
//                                    }
//
//                                    @Override
//                                    public void onResponse(Call call, Response response) throws IOException {
//                                        if (!response.isSuccessful()) {
//                                            System.err.println("Server responded with error: " + response.code());
//                                        } else {
//                                            // 处理成功的响应
//                                            System.out.println("Success: " + response.body().string());
//                                        }
//                                    }
//                                });

                                // 将数据写入CSV文件
                                CSVWriter.writeStringToCsv(internalStorageDir, dataStr, "left",username);
                                Log.e(TAG, TAG + " Left X:" + mpudata.mMpu[0] + " Y:" + mpudata.mMpu[1] + " Z:" + mpudata.mMpu[2]);
                                Log.e(TAG, TAG + " Left f1:" + fsrdata.mFsr[0] + " f2:" + fsrdata.mFsr[1] + " f3:" + fsrdata.mFsr[2] + " f4:" + fsrdata.mFsr[3]);
                                final String dataString = "Left X:" + mpudata.mMpu[0] + " Y:" + mpudata.mMpu[1] + " Z:" + mpudata.mMpu[2] +
                                        "\nLeft f1:" + fsrdata.mFsr[0] + " f2:" + fsrdata.mFsr[1] + " f3:" + fsrdata.mFsr[2] + " f4:" + fsrdata.mFsr[3];
                                handler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        leftInsoleDataTextView.setText(dataString);
                                    }
                                });
                                // 将dataString异步请求发送给服务器后端
                            }
                        }
                        else{
                            ArrayList<MpuData> mpulist = WalkingAnalysisServiceApi.getImuDataList(CommonAttribute.RIGHT_TYPE, arg0);
                            ArrayList<FsrData> fsrlist = WalkingAnalysisServiceApi.getFsrDataList(CommonAttribute.RIGHT_TYPE);
                            for (int i = 0; i < fsrlist.size(); i++) {
                                FsrData fsrdata = fsrlist.get(i);
                                MpuData mpudata = mpulist.get(i);
                                String dataStr = mpudata.mMpu[0] + " " + mpudata.mMpu[1] + " " + mpudata.mMpu[2]+" " + fsrdata.mFsr[0] + " " + fsrdata.mFsr[1] + " " + fsrdata.mFsr[2]+ " " + fsrdata.mFsr[3];
                                long timestamp = System.currentTimeMillis();

                                String rightInsoleData = String.valueOf(timestamp) + " " + dataStr;
                                // String url = "http://192.168.111.176:5000/rightInsoleData";
                                Map<String, String> dataMap = new HashMap<>();
                                dataMap.put("rightInsoleData", rightInsoleData);
                                dataMap.put("username", username);
                                // 创建一个 Gson 对象
                                Gson gson = new Gson();
                                // 将 Map 转换为 JSON 字符串
                                String jsonData = gson.toJson(dataMap);
                                // 异步发送数据
//                                NetUtil.sendPostAsync(NetConstant.SEND_RIGHTNSOLEDATA_URL, jsonData, new Callback() {
//                                    @Override
//                                    public void onFailure(Call call, IOException e) {
//                                        // 处理请求失败的情况
//                                        System.err.println("Failed to send data: " + e.getMessage());
//                                    }
//
//                                    @Override
//                                    public void onResponse(Call call, Response response) throws IOException {
//                                        if (!response.isSuccessful()) {
//                                            System.err.println("Server responded with error: " + response.code());
//                                        } else {
//                                            // 处理成功的响应
//                                            System.out.println("Success: " + response.body().string());
//                                        }
//                                    }
//                                });
                                // 将数据写入CSV文件
                                CSVWriter.writeStringToCsv(internalStorageDir,dataStr,"right",username);
                                Log.e(TAG, TAG+" Right X:" + mpudata.mMpu[0] + " Y:" + mpudata.mMpu[1] + " Z:" + mpudata.mMpu[2]);
                                Log.e(TAG, TAG+" Right f1:" + fsrdata.mFsr[0] + " f2:" + fsrdata.mFsr[1] + " f3:" + fsrdata.mFsr[2]+ " f4:" + fsrdata.mFsr[3]);
                                final String dataString = "Right X:" + mpudata.mMpu[0] + " Y:" + mpudata.mMpu[1] + " Z:" + mpudata.mMpu[2] +
                                        "\nRight f1:" + fsrdata.mFsr[0] + " f2:" + fsrdata.mFsr[1] + " f3:" + fsrdata.mFsr[2] + " f4:" + fsrdata.mFsr[3];
                                handler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        rightInsoleDataTextView.setText(dataString);
                                    }
                                });
                            }
                        }
                    }else{
                        try {
                            mWaitLock.wait(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            Log.e(TAG, TAG+"Thread end");
        }
    };




    private boolean checkPermissions() {
        int result;
        List<String> permissionList = new ArrayList<>();
        for (String pm : permissions) {
            result = ContextCompat.checkSelfPermission(mContext, pm);
            if (result != PackageManager.PERMISSION_GRANTED) { //사용자가 해당 권한을 가지고 있지 않을 경우 리스트에 해당 권한명 추가
                permissionList.add(pm);
            }
        }
        if (!permissionList.isEmpty()) { //권한이 추가되었으면 해당 리스트가 empty가 아니므로 request 즉 권한을 요청합니다.
            ActivityCompat.requestPermissions(getActivity(), permissionList.toArray(new String[permissionList.size()]), MULTIPLE_PERMISSIONS);
            return false;
        }
        return true;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case MULTIPLE_PERMISSIONS: {
                if (grantResults.length > 0) {
                    for (int i = 0; i < permissions.length; i++) {
                        if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                            showNoPermissionToastAndFinish();
                        }
                    }
                } else {
                    showNoPermissionToastAndFinish();
                }
                break;
            }
        }
    }

    private void showNoPermissionToastAndFinish() {
        Toast.makeText(mContext, "권한 요청에 동의 해주셔야 이용 가능합니다. 설정에서 권한 허용 하시기 바랍니다.", Toast.LENGTH_SHORT).show();
    }

    void ServiceStartCheck() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                String str = String.format(Locale.KOREA, "서비스 시작");
                Toast.makeText(mContext, str, Toast.LENGTH_SHORT).show();
                String[] data = WalkingAnalysisServiceApi.getUserInfo();
                if (data != null) {
                    data[WalkingAnalysisServiceApi.KEY_MY_FOOT_SIZE_INDEX] = "260";
                    data[WalkingAnalysisServiceApi.KEY_MY_AGE_INDEX] = "30";
                    data[WalkingAnalysisServiceApi.KEY_MY_HEIGHT_INDEX] = "180";
                    data[WalkingAnalysisServiceApi.KEY_MY_WEIGHT_INDEX] = "70";
                    data[WalkingAnalysisServiceApi.KEY_MY_SEX_INDEX] = "M";
                    data[WalkingAnalysisServiceApi.KEY_MY_NAME_INDEX] = "user";
                    data[WalkingAnalysisServiceApi.KEY_MY_EMAIL_INDEX] = "user@mgmail.co.kr";
                    WalkingAnalysisServiceApi.setUserInfo(data);
                }
                data = WalkingAnalysisServiceApi.getDeviceAddress();
                if (data != null) {
                    mLeftAddress = data[WalkingAnalysisServiceApi.KEY_LEFT_ADDRESS_INDEX];
                    mRightAddress = data[WalkingAnalysisServiceApi.KEY_RIGHT_ADDRESS_INDEX];
                    Log.e(TAG, "left insole addr " + mLeftAddress + " right insole addr " + mRightAddress);
                    if (mLeftAddress.equals("00:00:00:00:00:00") && mRightAddress.equals("00:00:00:00:00:01")) {
                        data[WalkingAnalysisServiceApi.KEY_LEFT_ADDRESS_INDEX] = mLeftAddress;
                        data[WalkingAnalysisServiceApi.KEY_RIGHT_ADDRESS_INDEX] = mRightAddress;
                        WalkingAnalysisServiceApi.setDeviceAddress(data);
                    }
                    WalkingAnalysisServiceApi.setDeviceAddress(data);
                }
            }
        });
    }


    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        internalStorageDir = requireContext().getFilesDir();

        viewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);

        // 初始化蓝牙管理器
        try {
            WitBluetoothManager.requestPermissions(requireActivity());
            WitBluetoothManager.initInstance(requireContext());
        } catch (Exception e) {
            Log.e("", e.getMessage());
            e.printStackTrace();
        }

        // 设置按钮点击事件
        Button startSearchButton = view.findViewById(R.id.startSearchButton);
        startSearchButton.setOnClickListener((v) -> {
            startDiscovery();
        });

        // 停止搜索按钮
        // stop search button
        Button stopSearchButton = view.findViewById(R.id.stopSearchButton);
        stopSearchButton.setOnClickListener((v) -> {
            stopDiscovery();
        });

        // 加计校准按钮
        // Acceleration calibration button
        Button appliedCalibrationButton = view.findViewById(R.id.appliedCalibrationButton);
        appliedCalibrationButton.setOnClickListener((v) -> {
            handleAppliedCalibration();
        });

        // 开始磁场校准按钮
        // Start Magnetic Field Calibration button
        Button startFieldCalibrationButton = view.findViewById(R.id.startFieldCalibrationButton);
        startFieldCalibrationButton.setOnClickListener((v) -> {
            handleStartFieldCalibration();
        });

        // 结束磁场校准按钮
        // End Magnetic Field Calibration button
        Button endFieldCalibrationButton = view.findViewById(R.id.endFieldCalibrationButton);
        endFieldCalibrationButton.setOnClickListener((v) -> {
            handleEndFieldCalibration();
        });

        // 读取03寄存器按钮
        // Read 03 register button
        Button readReg03Button = view.findViewById(R.id.readReg03Button);
        readReg03Button.setOnClickListener((v) -> {
            handleReadReg03();
        });

        // 自动刷新数据线程
        // Auto refresh data thread
        
        destroyed = false;
        startRefreshDataThread();

        // initChart();
    }



    private void startRefreshDataThread() {
        if (refreshDataThread == null || !refreshDataThread.isAlive()) {
            refreshDataThread = new Thread(this::refreshDataTh);
            refreshDataThread.start();
        }
    }


    /**
     * fragment与 activity不再关联时
     *
     * @author  liaozhaoping
     * @date 2024/5/21 15:53
     */
    @Override
    public void onDestroy() {

        super.onDestroy();
        destroyed = true;
    }



    @Override
    public void onDestroyView() {
        WalkingAnalysisServiceApi.destroyBleService();
        super.onDestroyView();
        destroyed = true;
        if (refreshDataThread != null) {
            refreshDataThread.interrupt();
        }
    }

    /**
     * 开始搜索设备
     * Start searching for devices
     *
     * @author huangyajun
     * @date 2022/6/29 10:04
     */
    public void startDiscovery() {

        // 关闭所有设备
        // Turn off all device
        for (int i = 0; i < bwt901clList.size(); i++) {
            Bwt901cl bwt901cl = bwt901clList.get(i);
            bwt901cl.removeRecordObserver(this);
            bwt901cl.close();
        }

        // 清除所有设备
        // Erase all devices
        bwt901clList.clear();

        // 开始搜索蓝牙
        // Start searching for bluetooth
        try {
            // 获得蓝牙管理器
            // get bluetooth manager
            WitBluetoothManager bluetoothManager = WitBluetoothManager.getInstance();
            // 注册监听蓝牙
            // Monitor communication signals
            bluetoothManager.registerObserver(this);
            // 指定要搜索的蓝牙名称
            // Specify the Bluetooth name to search for
            WitBluetoothManager.DeviceNameFilter = Arrays.asList("HC-06");
            // 开始搜索
            // start search
            bluetoothManager.startDiscovery();
        } catch (BluetoothBLEException e) {
            e.printStackTrace();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 停止搜索设备
     * Stop searching for devices
     *
     * @author huangyajun
     * @date 2022/6/29 10:04
     */
    public void stopDiscovery() {
        // 停止搜索蓝牙
        // stop searching for bluetooth
        try {
            // 获得蓝牙管理器
            // acquire Bluetooth manager
            WitBluetoothManager bluetoothManager = WitBluetoothManager.getInstance();
            // 取消注册监听蓝牙
            // Cancel monitor communication signals
            bluetoothManager.removeObserver(this);
            // 停止搜索
            // stop searching
            bluetoothManager.stopDiscovery();
        } catch (BluetoothBLEException e) {
            e.printStackTrace();
        }
    }

    /**
     * 当搜到蓝牙5.0设备时会回调这个方法
     * This method will be called back when a Bluetooth 5.0 device is found
     *
     * @author huangyajun
     * @date 2022/6/29 8:46
     */
    @Override
    public void onFoundBle(BluetoothBLE bluetoothBLE) {
    }

    /**
     * 当搜索到蓝牙2.0设备时会回调这个方法
     * This method will be called back when a Bluetooth 2.0 device is found
     *
     * @author huangyajun
     * @date 2022/6/29 10:01
     */
    @Override
    public void onFoundSPP(BluetoothSPP bluetoothSPP) {
    }

    /**
     * 找到双模蓝牙时
     * This method will be called back when data needs to be recorded
     *
     * @author huangyajun & liaozhaoping
     * @date 2022/6/29 8:46
     */
    @Override
    public void onFoundDual(BluetoothBLE bluetoothBLE) {
        // 创建蓝牙2.0传感器连接对象
        // Create a Bluetooth 2.0 sensor connection object
        Bwt901cl bwt901cl = new Bwt901cl(bluetoothBLE);
        // 避免重复连接
        // Avoid duplicate connections
        for (int i = 0; i < bwt901clList.size(); i++) {

            if (Objects.equals(bwt901clList.get(i).getMac(), bwt901cl.getMac())) {
                return;
            }
        }
        // 添加到设备列表
        // add to device list
        bwt901clList.add(bwt901cl);

        // 注册数据记录
        // Registration data record
        bwt901cl.registerRecordObserver(this);

        // 打开设备
        // Turn on the device
        try {
            bwt901cl.open();
        } catch (OpenDeviceException e) {
            // 打开设备失败
            // Failed to open device
            e.printStackTrace();
        }
    }

    /**
     * 当需要记录数据时会回调这个方法
     * This method will be called back when data needs to be recorded
     *
     * @author huangyajun & liaozhaoping
     * @date 2022/6/29 8:46
     */
    @Override
    public void onRecord(Bwt901cl bwt901cl) {
        String deviceData = getDeviceData(bwt901cl);

        try {
            StringToCSV.ToCSV(deviceData,internalStorageDir, bwt901cl.getDeviceName(),username);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // float[] acceleration = DataExtractor.extractAcceleration(deviceData);

        // Log.d(TAG, "onRecord: acceleration Size = " + acceleration.length);

        // viewModel.postFloatArray(acceleration);

        // viewModel.postDataString(deviceData);

        // addEntry(acceleration[0],acceleration[1],acceleration[2]);

        // netadress服务器地址
        // String url = "http://192.168.111.175:8080/greet";

        String mac = bwt901cl.getMac();
        String realData = StringToCSV.getWitData(deviceData);

        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("witData", realData);
        dataMap.put("username", username);
        dataMap.put("mac", mac);

        // 创建一个 Gson 对象
        Gson gson = new Gson();
        // 将 Map 转换为 JSON 字符串
        String jsonData = gson.toJson(dataMap);

        // 异步发送数据
//        NetUtil.sendPostAsync(NetConstant.SEND_WITDATA_URL, jsonData, new Callback() {
//            @Override
//            public void onFailure(Call call, IOException e) {
//                // 处理请求失败的情况
//                System.err.println("Failed to send data: " + e.getMessage());
//            }
//
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
//                if (!response.isSuccessful()) {
//                    System.err.println("Server responded with error: " + response.code());
//                } else {
//                    // 处理成功的响应
//                    System.out.println("Success: " + response.body().string());
//                }
//            }
//        });


        Log.d(TAG, "device data [ " + bwt901cl.getDeviceName() + "] = " + deviceData);
    }

    /**
     * 自动刷新数据线程
     * Auto refresh data thread
     *
     * @author huangyajun
     * @date 2022/6/29 13:41
     */
    private void refreshDataTh() {

        while (!destroyed) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (isAdded()) {
                Activity activity = getActivity();
                if (activity != null) {
                    activity.runOnUiThread(() -> {
                        StringBuilder text = new StringBuilder();
                        for (int i = 0; i < bwt901clList.size(); i++) {
                            Bwt901cl bwt901cl = bwt901clList.get(i);
                            String deviceData = getDeviceData(bwt901cl);
                            text.append(deviceData);
                            //Log.d("Debug", "Updating TextView with data: " + text.toString());
                        }
                        deviceDataTextView.setText(text.toString());
                    });
                } else {
                    Log.d("Debug", "Activity is null");
                }
            }
            else {
                Log.d("Debug", "Fragment not added to Activity");
            }

        }
    }

    /**
     * 获得一个设备的数据
     * Get a device's data
     *
     * @author huangyajun
     * @date 2022/6/29 11:37
     */
    private String getDeviceData(Bwt901cl bwt901cl) {
        StringBuilder builder = new StringBuilder();
        builder.append(bwt901cl.getDeviceName()).append("\n");
        builder.append(getString(R.string.accX)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.AccX))
                .append(WitSensorKey.AccX.getUnit()).append("\t");
        builder.append(getString(R.string.accY)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.AccY))
                .append(WitSensorKey.AccY.getUnit()).append("\t");
        builder.append(getString(R.string.accZ)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.AccZ))
                .append(WitSensorKey.AccZ.getUnit()).append("\n");
        builder.append(getString(R.string.asX)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.AsX))
                .append(WitSensorKey.AsX.getUnit()).append("\t");
        builder.append(getString(R.string.asY)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.AsY))
                .append(WitSensorKey.AsY.getUnit()).append("\t");
        builder.append(getString(R.string.asZ)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.AsZ))
                .append(WitSensorKey.AsZ.getUnit()).append("\n");
        builder.append(getString(R.string.angleX)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.AngleX))
                .append(WitSensorKey.AngleX.getUnit()).append("\t");
        builder.append(getString(R.string.angleY)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.AngleY))
                .append(WitSensorKey.AngleY.getUnit()).append("\t");
        builder.append(getString(R.string.angleZ)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.AngleZ))
                .append(WitSensorKey.AngleZ.getUnit()).append("\n");
        builder.append(getString(R.string.hX)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.HX))
                .append(WitSensorKey.HX.getUnit()).append("\t");
        builder.append(getString(R.string.hY)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.HY))
                .append(WitSensorKey.HY.getUnit()).append("\t");
        builder.append(getString(R.string.hZ)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.HZ))
                .append(WitSensorKey.HZ.getUnit()).append("\n");
        builder.append(getString(R.string.t)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.T))
                .append(WitSensorKey.T.getUnit()).append("\n");
        builder.append(getString(R.string.versionNumber)).append(":").append(bwt901cl.getDeviceData(WitSensorKey.VersionNumber))
                .append(WitSensorKey.VersionNumber.getUnit()).append("\n");
        return builder.toString();
    }

    /**
     * 让所有设备加计校准
     * Make all devices accelerometer calibrated
     *
     * @author huangyajun
     * @date 2022/6/29 10:25
     */
    private void handleAppliedCalibration() {
        for (int i = 0; i < bwt901clList.size(); i++) {
            Bwt901cl bwt901cl = bwt901clList.get(i);
            // 解锁寄存器
            // unlock register
            bwt901cl.unlockReg();
            // 发送命令
            // send command
            bwt901cl.appliedCalibration();
        }
        Toast.makeText(requireActivity(), "OK", Toast.LENGTH_LONG).show();
    }

    /**
     * 让所有设备开始磁场校准
     * Let all devices begin magnetic field calibration
     *
     * @author huangyajun
     * @date 2022/6/29 10:25
     */
    private void handleStartFieldCalibration() {
        for (int i = 0; i < bwt901clList.size(); i++) {
            Bwt901cl bwt901cl = bwt901clList.get(i);
            // 解锁寄存器
            // unlock register
            bwt901cl.unlockReg();
            // 发送命令
            // send command
            bwt901cl.startFieldCalibration();
        }
        Toast.makeText(requireActivity(), "OK", Toast.LENGTH_LONG).show();
    }

    /**
     * 让所有设备结束磁场校准
     * Let's all devices end the magnetic field calibration
     *
     * @author huangyajun
     * @date 2022/6/29 10:25
     */
    private void handleEndFieldCalibration() {
        for (int i = 0; i < bwt901clList.size(); i++) {
            Bwt901cl bwt901cl = bwt901clList.get(i);
            // 解锁寄存器
            // unlock register
            bwt901cl.unlockReg();
            // 发送命令
            // send command
            bwt901cl.endFieldCalibration();
        }
        Toast.makeText(requireActivity(), "OK", Toast.LENGTH_LONG).show();
    }


    /**
     * 读取03寄存器的数据
     * Read 03 register data
     *
     * @author huangyajun
     * @date 2022/6/29 10:25
     */
    private void handleReadReg03() {
        for (int i = 0; i < bwt901clList.size(); i++) {
            Bwt901cl bwt901cl = bwt901clList.get(i);
            // 必须使用 sendProtocolData 方法，使用此方法设备才会将寄存器值读取上来
            // Must be used sendProtocolData method, and the device will read the register value when you using this method
            int waitTime = 200;
            // 发送指令的命令,并且等待200ms
            // The command to send the command, and wait 200ms
            bwt901cl.sendProtocolData(new byte[]{(byte) 0xff, (byte) 0xAA, (byte) 0x27, (byte) 0x03, (byte) 0x00}, waitTime);
            // 获得寄存器03的值
            // get the value of register 03
            Short reg03Value = bwt901cl.getDeviceData(new ShortKey("03"));
            // 如果读上来了 reg03Value 就是寄存器的值，如果没有读上来可以将 waitTime 放大,或者多读几次
            // If it is read up, reg03Value is the value of the register. If it is not read up, you can enlarge waitTime, or read it several times.v
            Toast.makeText(requireActivity(), bwt901cl.getDeviceName() + " reg03Value: " + reg03Value, Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void OnServiceCreated(int result) {
        Log.e(TAG,"Service create result: " + result);
        ServiceStartCheck();
    }

    @Override
    public void OnConnected(int lr_type,int status) {

        if(status == 0) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(mContext, "connected insole Successful", Toast.LENGTH_SHORT).show();
                }
            });
        }

        Log.e(TAG,"onConnect lr_type " + lr_type +  " status " + status);
    }

    @Override
    public void OnDisconnected(int lr_type,int status) {
        Log.e(TAG,"OnDisconnected lr_type " + lr_type +  " status " + status);
        if (status == 0 ) {
            // 再次尝试连接
            WalkingAnalysisServiceApi.bleConnect((byte) 0, false, false);
        } else {
            System.out.println("重新连接失败。");
        }
    }


    @Override
    public void OnLeftRealData(byte[] bytes) {
        DataQueuePacket qPacket = new DataQueuePacket();
        qPacket.setData(CommonAttribute.LEFT_TYPE,bytes);
        dataQueue.offer(qPacket);
        synchronized (mWaitLock){
            mWaitLock.notify();
        }
    }

    @Override
    public void OnRightRealData(byte[] bytes) {
        DataQueuePacket qPacket = new DataQueuePacket();
        qPacket.setData(CommonAttribute.RIGHT_TYPE,bytes);
        dataQueue.offer(qPacket);
        synchronized (mWaitLock){
            mWaitLock.notify();
        }
    }

    @Override
    public void OnStorageATData(ATData atData) {
        Log.e(TAG,"OnStorageATData :" + atData);

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {

                if(atData.mDate > 0){
                    java.util.Date dt = new java.util.Date(atData.mDate);
                    SimpleDateFormat sdfNow = new SimpleDateFormat("yyyyMMdd-HHmmss");

                    if(atData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG, "OnStorageATData DAY : " +
                                ", mDate = " + sdfNow.format(dt) + ", mDataType = " + atData.mDataType +
                                ", mCalories = "  + atData.mCalories + ", mDistance = " + (atData.mWalkingDistance+atData.mRunningDistance) +
                                ", mLR_Type = " + atData.mLR_Type + ", mStepCount = " + (atData.mWalkingStepCount+atData.mRunningStepCount));

                    }else if(atData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG, "OnStorageATData HOUR : " +
                                ", mDate = " + sdfNow.format(dt) + ", mDataType = " + atData.mDataType +
                                ", mCalories = "  + atData.mCalories + ", mDistance = " + (atData.mWalkingDistance+atData.mRunningDistance) +
                                ", mLR_Type = " + atData.mLR_Type + ", mStepCount = " + (atData.mWalkingStepCount+atData.mRunningStepCount));
                    }
                }else{
                    // 인솔에서 제공해줄 데이터가 없다.
                    // There is no data provided by Insole.
                    if(atData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG,"day data no");
                    }else if(atData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG,"hour data no");
                    }
                }
            }
        });

    }

    @Override
    public void OnStorageAAData(AAData aaData) {
        Log.e(TAG,"OnStorageAAData :" + aaData);

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {

                if(aaData.mDate > 0){
                    java.util.Date dt = new java.util.Date(aaData.mDate);
                    SimpleDateFormat sdfNow = new SimpleDateFormat("yyyyMMdd-HHmmss");

                    if(aaData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG, "OnStorageAAData DAY : " + aaData.toString());

                    }else if(aaData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG, "OnStorageAAData HOUR : " + aaData.toString());
                    }
                }else{
                    // 인솔에서 제공해줄 데이터가 없다.
                    // There is no data provided by Insole.
                    if(aaData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG,"day data no");
                    }else if(aaData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG,"hour data no");
                    }
                }
            }
        });



    }

    @Override
    public void OnStorageGAData(GAData gaData) {
        Log.e(TAG,"OnStorageGAData :mDate:" + gaData.mDate + " mPreDate:" + gaData.mPreDate);

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                /*
                 mDate 순서
                 ## 데이터가 있을때
                     mDate == -2(유효 데이터 , 다음 데이터 요청한다)
                     -> mDate == 0(인솔 더이상 데이터가 없다, end)
                     -> mDate > 0(라이브러리에서 처리한 데이터 보내줌)
                     -> mDate == -3(라이브러리에서 더이상 데이터 없음 , end)의 순서대로 온다.

                 ## 데이터가 없다면 mDate == 0 -> mDate == -3 의 순서대로 온다.

                 mDate order
                 ## When there is data
                     mDate == -2 (valid data, request next data)
                     -> mDate == 0 (there is no more data, end)
                     -> mDate > 0 (data processed by the library is sent)
                     -> mDate == -3 (no more data in the library, end).

                 ## If there is no data, it comes in the following order: mDate == 0 -> mDate == -3.

                */

                /*
                    왼발 데이터 요청한다.
                    -> 데이터 있으면 (mDate == -2)
                        -> 다시 왼발 요청한다.(데이터가 0일 때 까지)
                    -> 데이터 없으면 (mDate == 0)
                        -> 오른발 데이터 요청

                    오른발 데이터 요청한다.
                     -> 데이터 있으면 (mDate == -2)
                       -> 다시 오른발 데이터 요청한다.(데이터가 0일 때 까지)
                     -> 데이터 없으면 (mDate == 0)
                       -> 라이브러리에서 (mDate > 0) 큰 값으로  전달한다.

                     mDate >0 큰 수
                     왼발 값 들어오고 계속 들어온다(유효 데이터).
                     다 들어오면 (mDate == -3) 값을 준다(유효 데이터 종료).
                     그리고 오른발 (mDate >0) 값으로 계속 들어온다(유효 데이터).
                     다 들어오면 (mDate == -3) 값을 준다(유효 데이터 종료).

                     오른발 (mDate == -3)의 값을 받으면 완료된 상태이다.

                     Request left foot data.
                        -> If there is data (mDate == -2)
                           -> Request the left foot again (until the data is 0)
                        -> If there is no data (mDate == 0)
                           -> Right foot data request

                    Request right foot data.
                        -> If there is data (mDate == -2)
                           -> Request right foot data again (until data is 0)
                        -> If there is no data (mDate == 0)
                           -> In the library, (mDate > 0) is passed as a large value.

                     mDate >0 large number
                     The left foot value comes in and continues to come in (valid data).
                     When everything comes in, a value (mDate == -3) is given (valid data ends).
                     And the right foot (mDate >0) value continues to come in (valid data).
                     When everything comes in, a value (mDate == -3) is given (valid data ends).

                     If you receive the value of the right foot (mDate == -3), it is complete.
                */

                if(gaData.mDate > 0){
                    java.util.Date dt = new java.util.Date(gaData.mDate);
                    SimpleDateFormat sdfNow = new SimpleDateFormat("yyyyMMdd-HHmmss");

                    if(gaData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG, "OnStorageGAData DAY : " + gaData.toString());

                    }else if(gaData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG, "OnStorageGAData HOUR : " + gaData.toString());
                    }
                }
                else if(gaData.mDate == -2){
                    /*
                     다음 데이터 요청 또는 mPreDate를 이용하여 해당 날짜의 데이터로 이용할 수 있다.
                     You can use the data for that date by requesting the following data or using mPreDate.
                    */
                    java.util.Date dt = new java.util.Date(gaData.mPreDate);
                    SimpleDateFormat sdfNow = new SimpleDateFormat("yyyyMMdd-HHmmss");

                    if(gaData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG, "OnStorageGAData DAY : " + gaData.toString());

                    }else if(gaData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG, "OnStorageGAData HOUR : " + gaData.toString());
                    }
                }
                else if(gaData.mDate == -3){
                    /*
                     데이터가 없다. 라이브러리에서 모두 전달했다.
                     There is no data. All delivered by the library.
                    */

                    if(gaData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG,"day data no");
                    }else if(gaData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG,"hour data no");
                    }

                }
                else if(gaData.mDate == 0){
                    /*
                     인솔에서 제공해줄 데이터가 없다.다음 데이터 요청 한다.
                     다음 데이터 요청(mData == -3)이 나오도록 하기 위해서이다.
                     There is no data to provide from Insole. Request the following data.
                     This is to ensure that the next data request (mData == -3) is issued.
                    */
                    if(gaData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG,"day data no");
                    }else if(gaData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG,"hour data no");
                    }
                }
            }
        });

    }

    @Override
    public void OnInitializeCompleted() {
        Log.e(TAG,"OnInitializeCompleted Left , Right All Connected");
        ((Activity) mContext).runOnUiThread(new Runnable() {
            public void run() {
                // 매번 접속시 사용자 변경 데이터 넣어준다.
                // User change data is entered every time you connect.
                WalkingAnalysisServiceApi.setDeviceInformation((byte)CommonAttribute.REGISTER_TYPE_CHANGE_USERINFO);
            }
        });
    }

    @Override
    public void OnStorageMVData(MVData mvData) {
        Log.e(TAG,"OnStorageMVData :mDate:" + mvData.mDate + " mPreDate:" + mvData.mPreDate);
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {


                if(mvData.mDate > 0){
                    java.util.Date dt = new java.util.Date(mvData.mDate);
                    SimpleDateFormat sdfNow = new SimpleDateFormat("yyyyMMdd-HHmmss");

                    if(mvData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG, "OnStorageMVData DAY : " + mvData.toString());

                    }else if(mvData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG, "OnStorageMVData HOUR : " + mvData.toString());
                    }
                }
                else if(mvData.mDate == -2){
                    /*
                     다음 데이터 요청 또는 mPreDate를 이용하여 해당 날짜의 데이터로 이용할 수 있다.
                     You can use the data for that date by requesting the following data or using mPreDate.
                    */
                    java.util.Date dt = new java.util.Date(mvData.mPreDate);
                    SimpleDateFormat sdfNow = new SimpleDateFormat("yyyyMMdd-HHmmss");

                    if(mvData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG, "OnStorageMVData DAY : " + mvData.toString());

                    }else if(mvData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG, "OnStorageMVData HOUR : " + mvData.toString());
                    }
                }
                else if(mvData.mDate == -3){
                    /*
                     데이터가 없다. 라이브러리에서 모두 전달했다.
                     There is no data. All delivered by the library.
                    */

                    if(mvData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG,"day data no");
                    }else if(mvData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG,"hour data no");
                    }

                }
                else if(mvData.mDate == 0){
                    /*
                     인솔에서 제공해줄 데이터가 없다.다음 데이터 요청 한다.
                     다음 데이터 요청(mData == -3)이 나오도록 하기 위해서이다.
                     There is no data to provide from Insole. Request the following data.
                     This is to ensure that the next data request (mData == -3) is issued.
                    */
                    if(mvData.mDataType == CommonAttribute.FLASH_DAY_DATA){
                        Log.e(TAG,"day data no");
                    }else if(mvData.mDataType == CommonAttribute.FLASH_HOUR_DATA){
                        Log.e(TAG,"hour data no");
                    }
                }
            }
        });


    }

    @Override
    public void OnATData(ATData atData) {

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.e(TAG,"OnATData:"+atData.toString());

                // OnSAData callback
                WalkingAnalysisServiceApi.getStatistics();
            }
        });

    }

    @Override
    public void OnAAData(AAData aaData) {

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.e(TAG,"OnAAData:"+aaData.toString());
            }
        });
    }

    @Override
    public void OnGAData(GAData gaData) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.e(TAG,"OnGAData:"+gaData.toString());
            }
        });
    }

    @Override
    public void OnMVData(MVData mvData) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.e(TAG,"OnMVData:"+mvData.toString());
            }
        });
    }

    @Override
    public void OnSAData(SAData saData) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.e(TAG,"OnSAData:"+saData.toString());
            }
        });
    }


    @Override
    public void OnDeviceInfomation(int lr_type,DeviceInfo info,int command_type) {
        Log.e(TAG,"OnDeviceInfomation lr_type" + lr_type + " info " +info.toString());
    }


    @Override
    public void OnRealtime(int lr_type,byte enable) {
        Log.e(TAG,"OnRealtime lr_type" + lr_type + " enable " +enable);
    }

    @Override
    public void OnRequestStatus(int lr_type,byte status) {
        Log.e(TAG,"OnRequestStatus lr_type" + lr_type + " status " +status);
    }

    @Override
    public void OnClearHistory(int lr_type,byte cleartype,byte done) {
        Log.e(TAG,"OnClearHistory lr_type" + lr_type + " cleartype " +cleartype + " done:" +done);
    }

    @Override
    public void OnClearAll(int lr_type,byte done) {
        Log.e(TAG,"OnClearAll lr_type" + lr_type + " done:" +done);
    }

    @Override
    public void OnGetVersion(int lr_type,byte hwv,byte fwv,int bv,int finaltest) {
        Log.e(TAG,"OnGetVersion lr_type" + lr_type + " hwv:" +hwv + " fwv:"+fwv + " bv:"+bv + " finaltest:"+finaltest);
    }

    @Override
    public void OnGetFWStatus(int lr_type, int batterylevel,
                              int currentrtc, int temperature, int memsstatus,
                              int memsenable, int fsrstatus, int fsrenable,int bootcount) {

        // GMT Data Korea
        TimeZone tz = TimeZone.getDefault();
        // currentrtc 안에는 GMT + TIME ZONE이 들어가 있다. 그래서 TIME ZONE 만큼 뺐다.
        // Currentrtc contains GMT + TIME ZONE. So it's all about TIME ZONE.
        Date dt = new Date(currentrtc*1000L);
        SimpleDateFormat sdfNow = new SimpleDateFormat("yyyy_MM_dd HH_mm_ss", Locale.getDefault());
        if(ApiBuildConfig.DEBUG)Log.e(TAG,"currentrtc*1000L Date " + sdfNow.format(dt));

        // currentrtc 안에는 GMT + TIME ZONE이 들어가 있다. 그래서 TIME ZONE 만큼 뺐다.
        // Currentrtc contains GMT + TIME ZONE. So it's all about TIME ZONE.
        dt = new Date(currentrtc*1000L - tz.getRawOffset());
        sdfNow = new SimpleDateFormat("yyyy_MM_dd HH_mm_ss", Locale.getDefault());
        Log.e(TAG,"currentrtc*1000L - tz.getRawOffset() Date " + sdfNow.format(dt) + " offset " + tz.getRawOffset());



        Log.e(TAG,"OnGetFWStatus " + lr_type +  " batterylevel " + batterylevel + " currentrtc " + currentrtc + " temperature " + temperature
                + " memsenable " + memsenable + " memsstatus " + memsstatus + " fsrstatus " + fsrstatus + " fsrenable " + fsrenable);

    }

    @Override
    public void OnScanData(ScanData scanData) {
        Log.e(TAG,"OnScanData " + scanData.toString());
//        Log.d(TAG, "OnScanDataAddress: " + scanData.getDeviceAddress());
        // 从 scanData 中获取设备地址
        String deviceAddress = scanData.getDeviceAddress();

        if (mDeviceAddresses[0] == null && scanData.getDeviceName().equals("PSPODL")) {
            mDeviceAddresses[0] = deviceAddress;
            mLeftAddress = deviceAddress;
        } else if (mDeviceAddresses[1] == null && scanData.getDeviceName().equals("PSPODR") /*mDeviceAddresses[0] != deviceAddress*/) {
            mDeviceAddresses[1] = deviceAddress;
            mRightAddress = deviceAddress;
        }

        // Modify the value of PreferenceData
        if(mDeviceAddresses[0] != null && mDeviceAddresses[1] != null ) {
            String[] deviceInfoPreference = PreferenceData.getDeviceInfoPreference(getContext());

            deviceInfoPreference[PreferenceData.left_device_address_index] = mDeviceAddresses[0];
            deviceInfoPreference[PreferenceData.right_device_address_index] = mDeviceAddresses[1];
            PreferenceData.setDeviceInfoPreference(mContext,deviceInfoPreference);

            if (mDeviceAddresses[0] != null && mDeviceAddresses[1] != null) {
                // 인솔이 검색이 되었다면 scan stop 한다.
                // If the insole is searched, scan stop.
                WalkingAnalysisServiceApi.stopDeviceScan();
                // 弹出消息提示扫描结束
                // java.lang.NullPointerException: Can't toast on a thread that has not called Looper.prepare()
                // Toast.makeText(mContext, "Scan finished", Toast.LENGTH_SHORT).show();
                Handler handler1 = new Handler(Looper.getMainLooper());
                handler1.post(new Runnable() {
                    @Override
                    public void run() {
                        // 更新UI
                        // Update UI
                        Toast.makeText(mContext, "Scan finished", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }

    }

    @Override
    public void OnUpdateProgress(String lr_type_address,int value) {
        Log.e(TAG,"OnUpdateProgress lr_type_address" + lr_type_address + " value:" +value);
    }

    @Override
    public void OnUpdateResult(String lr_type_address,int result) {
        Log.e(TAG,"OnUpdateResult lr_type_address" + lr_type_address + " result:" +result);
    }

    @Override
    public void OnSetFindDevice(int lr_type,int enablemode) {
        Log.e(TAG,"OnSetFindDevice " + lr_type + " enablemode " + enablemode );
    }

    @Override
    public void OnGetFindDevice(int lr_type, int mode, int enable) {
        Log.e(TAG,"OnGetFindDevice " + lr_type + " mode " + mode + " detected " + enable );

    }

    @Override
    public void OnRunningStartStop(RunningData runningData) {
        Log.e(TAG,"OnRunningStartStop  runningData:"+runningData);
    }

    @Override
    public void OnRunningGetSection(RunningSectionData runningSectionData) {
        Log.e(TAG,"OnRunningGetSection  runningSectionData:"+runningSectionData);
    }
}